#ifndef TOKEN_H
#define TOKEN_H

#include <string>
#include <boost/shared_ptr.hpp>
#include "errors.h"

class Token : public Location
{
public:
   typedef boost::shared_ptr<Token> Ptr;

   typedef enum
   {
      T_EOF,
      T_UNKNOWN_SYMBOL,
      T_UNEXPECTED_CHAR,

      T_NIL,
      T_TRUE,
      T_FALSE,

      T_EQ,
      T_NE,
      T_LT,
      T_GT,
      T_LE,
      T_GE,

      T_NOT,
      T_AND,
      T_OR,
      T_XOR,

      T_LSHIFT,
      T_RSHIFT,

      T_IF,
      T_ELSE,
      T_RETURN,

      T_LBRACE,
      T_RBRACE,
      T_LPAREN,
      T_RPAREN,
      T_LBRACKET,
      T_RBRACKET,
      T_LANGLE,
      T_RANGLE,
      T_COMMA,
      T_DOT,
      T_TYPE_SEPARATOR,
      T_TERMINATOR,

      T_ASSIGN,
      T_PLUS,
      T_MINUS,
      T_STAR,
      T_DIVIDE,
      T_MOD,
      T_POWER,

      T_BINARY,
      T_HEXADECIMAL,
      T_INTEGER,
      T_REAL,
      T_IMAGINARY,
      T_STRING,

      T_IDENTIFIER,
      T_MEMBER,
      T_TYPE,
      T_WEAK,

      T_THIS,
      T_SUPER,

      T_IMPORT,
      T_ENUM,
      T_CLASS,
      T_IMMUTABLE,
      T_INTERFACE,

      T_INCLUDES,
      T_EXTENDS,
      T_IMPLEMENTS,
      T_WHERE,

      T_LITERAL,

      T_PROTECTED,
      T_PACKAGE,
      T_PUBLIC,
      T_NEW,
      T_RESULTS,
      T_THROWS,

      T_VAR
   } type_t;

protected:
   typedef struct
   {
      const std::string data;
      const Token::type_t type;
   } lookup_t;

   static const lookup_t keywords[];
   static const lookup_t symbols[];
   static const std::string none;

   type_t _type;
   std::string _data;

public:
	Token( const Location& loc, type_t type );

   static const std::string& text( type_t type );
   static bool is_symbol( const std::string& data );

   inline type_t type() const { return _type; }
   const std::string& string() const;

   void mutate( type_t type );
   void finalize( const std::string& data );
};

#endif // TOKEN_H
